#pragma once
#include <pthread.h>
#include <iostream>
#include <queue>
#include <typeinfo>
using namespace std;
template <typename T>
class thread_pool_t
{
private:
    //单例模式
    thread_pool_t(size_t thread_num = 5)
        : _thread_num(thread_num), _is_running(false), _queue()
    {
        pthread_mutex_init(&_queue_mutex, nullptr);
        pthread_cond_init(&_task_condition, nullptr);
    }
    thread_pool_t(thread_pool_t<T> &thread_pool) = delete;
    // operator =(thread_pool_t<T>&thread_pool)=delete;//用赋值重载构造对象,会被转换成构造/拷贝构造(都不成立)
public:
    static thread_pool_t<T> *get_thread_pool_instance(int thread_num = 5)
    {
        if (_this)
            return _this;
        else
        {
            static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
            pthread_mutex_lock(&mutex);
            if (_this == nullptr)
                _this = new thread_pool_t<T>(thread_num);
            pthread_mutex_unlock(&mutex);
        }
        return _this;
    }
    //专用于垃圾回收的内部类
    struct thread_pool_recycler_t
    {
        ~thread_pool_recycler_t()
        {
            delete _this;
        }
    };
    ~thread_pool_t()
    {
        pthread_mutex_destroy(&_queue_mutex);
        pthread_cond_destroy(&_task_condition);
    }

public:
    bool start()
    {
        if (!_is_running)
        {
            create_thread();
            return true;
        }
        cerr << "Already started!" << endl;
        return false;
    }
    //接收任务
    void push(T &task)
    {
        pthread_mutex_lock(&_queue_mutex);
        {
            _queue.push(task);
        }
        pthread_mutex_unlock(&_queue_mutex);
        assign_task();
    }
    //右值版本,支持lambda表达式
    void push(T &&task)
    {
        pthread_mutex_lock(&_queue_mutex);
        {
            _queue.push(task);
        }
        pthread_mutex_unlock(&_queue_mutex);
        assign_task();
    }

private:
    bool have_task() { return !_queue.empty(); }
    //唤醒等待的线程
    void assign_task() { pthread_cond_signal(&_task_condition); }
    T pop()
    {
        T ret = _queue.front();
        _queue.pop();
        return ret;
    }
    static void *thread_routine(void *argc)
    {
        pthread_detach(pthread_self());
        thread_pool_t *p_this = static_cast<thread_pool_t *>(argc);
        while (1)
        {
            //获取任务
            T task = T();
            pthread_mutex_lock(&(p_this->_queue_mutex));
            //临界区
            {
                //没有任务就利用条件变量释放锁等待指派任务
                while (!(p_this->have_task()))
                {
                    pthread_cond_wait(&(p_this->_task_condition), &(p_this->_queue_mutex));
                }
                task = p_this->pop();
            }
            pthread_mutex_unlock(&(p_this->_queue_mutex));
            //执行任务
            cout << "线程"
                 << "[" << pthread_self() << "]"
                 << ":";
            task();
        }
    }
    void create_thread()
    {
        for (int i = 0; i < _thread_num; i++)
        {
            pthread_t tid;
            pthread_create(&tid, nullptr, thread_routine, static_cast<void *>(this));
        }
    }

private:
    bool _is_running;
    size_t _thread_num;
    queue<T> _queue;
    pthread_mutex_t _queue_mutex;
    pthread_cond_t _task_condition;
    //单例模式
    //这两个成员再类外初始化,需注意声明顺序,保证析构顺序,垃圾回收类会自动清理资源
    static thread_pool_recycler_t thread_pool_recycler;
    static thread_pool_t<T> *_this;
};
//单例模式
template <class T>
thread_pool_t<T> *thread_pool_t<T>::_this{nullptr};
template <class T>
typename thread_pool_t<T>::thread_pool_recycler_t thread_pool_t<T>::thread_pool_recycler{};